package com.itmuch.box.service.member;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.itmuch.box.core.base.BaseService;
import com.itmuch.box.core.constant.ConstantRedis;
import com.itmuch.box.core.exception.BusinessException;
import com.itmuch.box.dao.member.MemberRepository;
import com.itmuch.box.domain.member.entity.Member;
import com.itmuch.box.domain.member.vo.MemberRegVo;
import com.itmuch.box.service.redis.RedisStringService;
import com.itmuch.box.util.DozerUtil;
import com.itmuch.box.util.IPUtil;
import com.itmuch.box.util.PasswordEncoderUtil;
import com.itmuch.box.util.TimeUtil;
import com.itmuch.box.util.mail.MailSendUtil;

@Service
@Transactional(rollbackFor = Exception.class)
public class MemberService extends BaseService<MemberRepository, Member> {
    @Autowired
    private MailSendUtil mailSendUtil;
    @Autowired
    private RedisStringService redisStringService;

    public Member findByKeys(String username, String email) {
        List<Member> list = this.dao.findByKeys(username, email);
        if (!list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

    public Member login(String email, String password) {
        return this.dao.findByEmailAndPassword(email, password);
    }

    /**
     * 异步发送验证码到邮箱, 并插入f_member表.
     * @param regVo
     * @param request
     * @throws BusinessException
     */
    @Async
    public Future<Boolean> reg(MemberRegVo regVo, HttpServletRequest request) {

        try {
            Member member = DozerUtil.map(regVo, Member.class);
            String email = regVo.getEmail();
            String vcode = UUID.randomUUID().toString();
            // 1. 发送邮件
            this.mailSendUtil.sendRegEmail(email, vcode);

            // 2. 插入到f_member表中
            String password = regVo.getPassword();
            String encodedPwd = PasswordEncoderUtil.encode(password);
            member.setPassword(encodedPwd);

            member.setRegIp(IPUtil.getIpAddress(request));
            member.setRegTime(TimeUtil.now());
            this.insert(member);

            Integer id = member.getId();

            // 4. 将邮箱认证码放入缓存, key:VCode,value: 用户id
            this.redisStringService.set(ConstantRedis.REG_EMAIL_PREFIX + vcode, String.valueOf(id), 24L, TimeUnit.HOURS);

            return new AsyncResult<Boolean>(true);
        } catch (BusinessException e) {
            return new AsyncResult<Boolean>(false);
        }
    }

    public void bindEmail(String vcode, Integer id) {
        Member member = this.dao.findOne(id);
        member.setId(id);
        member.setBindEmailFlag((byte) 1);
        member.setBindMobileFlag((byte) 1);

        // 1. 将用户的bind_email_flag 设为1
        this.update(member);

        // 2. 删除缓存
        this.redisStringService.deleteByKey(ConstantRedis.REG_EMAIL_PREFIX + vcode);
    }

    // TODO
    //    public Page<Member> findAll(Pageable pageable) {
    //        return this.memberRepository.findAll(pageable);
    //    }
    /*public Page<Member> findByCondition(Member condition, Pageable pageable) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("LIKE_username", condition.getUsername());
        map.put("LIKE_email", condition.getEmail());
        Map<String, SearchFilter> parse = SearchFilter.parse(map);
        Specification<Member> specification = DynamicSpecifications.bySearchFilter(parse.values(), Member.class);
        Page<Member> page = this.memberRepository.findAll(specification, pageable);
    
        Page<Member> page = this.memberRepository.findAll(new Specification<Member>() {
            @Override
            public Predicate toPredicate(Root<Member> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<String> usernamePath = root.get("username");
                Path<String> emailPath = root.get("email");
                Predicate like = cb.like(usernamePath, "%" + condition.getUsername() + "%");
                Predicate like2 = cb.like(emailPath, "%" + condition.getEmail() + "%");
                query.where(like, like2);
                return null;
            }
        }, pageable);
    
        return page;
    }*/
}
